<?php namespace App\Http\Controllers;

use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\Topic;
use App\Models\Reply;
use App\Models\UserPointsLog;
use App\Models\UserDcoinsLog;
use App\Models\UserSignLog;
use App\Models\UserVipInfo;
use App\Models\ArticleArchieve;
use App\Models\YzPayment;
use Illuminate\Http\Request;
use DB;
use Illuminate\Support\Facades\Redis;
use Mockery\Exception;
use Phphub\Github\GithubUserDataReader;
use Cache;
use Auth;
use Flash;
use App\Http\Requests\UpdateUserRequest;
use App\Http\Requests\ResetPasswordRequest;
use App\Jobs\SendActivateMail;
use App\Jobs\CheckYzTrade;
use Phphub\Handler\Exception\ImageUploadException;
use App\Activities\UserFollowedUser;

use App\Pay\Youzan;

use Carbon\Carbon;

use Mail;
use Illuminate\Mail\Message;
use Naux\Mail\SendCloudTemplate;

class UsersController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth', ['except' => [
            'index', 'show', 'replies',
            'topics', 'articles', 'votes', 'following',
            'followers', 'githubCard', 'githubApiProxy', 'sign'
        ]]);
    }

    public function index()
    {
        $users = User::recent()->take(48)->get();

        return view('users.index', compact('users'));
    }

    public function show($id)
    {
        $user = User::findOrFail($id);
        $topics = Topic::whose($user->id)->withoutArticle()->withoutBoardTopics()->recent()->limit(20)->get();
        $articles = Topic::whose($user->id)->onlyArticle()->withoutDraft()->recent()->with('blogs')->limit(20)->get();
        $blog = $user->blogs()->first();
        $replies = Reply::whose($user->id)->recent()->limit(20)->get();
        return view('users.show', compact('user', 'blog', 'articles', 'topics', 'replies'));
    }

    public function edit($id)
    {
        $user = User::findOrFail($id);
        $this->authorize('update', $user);

        return view('users.edit', compact('user', 'topics', 'replies'));
    }

    public function update($id, UpdateUserRequest $request)
    {
        $user = User::findOrFail($id);
        $this->authorize('update', $user);
        try {
            $request->performUpdate($user);
            Flash::success(lang('Operation succeeded.'));
        } catch (ImageUploadException $exception) {
            Flash::error(lang($exception->getMessage()));
        }

        return redirect(route('users.edit', $id));
    }

    /*
     * 充D币
     */
    public function chargeDcoin($id)
    {
        $price = 10;
        $user = User::findOrFail($id);
        $latestUDcoinLog = UserDcoinsLog::getLatestUDcoinLog($user->id);
        $remain_dcoin = 0;
        $qr_img = null;
        $qr_id = 0;
        if (!empty($latestUDcoinLog) && !empty($latestUDcoinLog['remain_points'])) {
            $remain_dcoin = $latestUDcoinLog['remain_dcoins'];
        }
        //创建有赞支付二维码
//        $qr = Youzan::createQRCode($price);
//        $payment_type = YzPayment::TYPE_DCOINS;
//        if (!empty($qr)) {
//            $qr_img = $qr['qr_code'];
//            $qr_id = $qr['qr_id'];
//
//            $yz_payment_arr = ['user_id' => $user->id, 'qr_id' => $qr['qr_id'],
//                'qr_price' => $price, 'status' => YzPayment::TRADE_NOT_PAY,
//                'type' => YzPayment::TYPE_DCOINS, 'vip_id' => 0,
//                'created_at' => Carbon::now(), 'updated_at' => Carbon::now()];
//
//            $payment_id = DB::table('yz_payments')->insertGetId($yz_payment_arr);
//        }


//        return view('users.dcoin_charge', compact('remain_dcoin', 'user', "qr_img", 'qr_id', 'price', 'payment_id', 'payment_type'));
        return view('users.dcoin_charge', compact('remain_dcoin', 'user'));
    }

    /*
     * 创建有赞支付二维码
     */
    public function makeChargeQR($id, $price, $type, Request $request)
    {
        $user = User::findOrFail($id);

        $qr_img = null;
        $qr_id = 0;

        //创建有赞支付二维码
        $qr = Youzan::createQRCode($price);
        if (!isset($price) || $price < 10) {
            $price = 10;
        }

        if (!empty($qr)) {
            $vip_id = $request->input('vip_id');

            $qr_img = $qr['qr_code'];
            $qr_id = $qr['qr_id'];

            $yz_payment_arr = ['user_id' => $user->id, 'qr_id' => $qr['qr_id'],
                'qr_price' => $price, 'status' => YzPayment::TRADE_NOT_PAY,
                'type' => $type, 'vip_id' => ($type == YzPayment::TYPE_VIP ? $vip_id : 0),
                'created_at' => Carbon::now(), 'updated_at' => Carbon::now()];
            $payment_id = DB::table('yz_payments')->insertGetId($yz_payment_arr);
            //$payment_id = YzPayment::getInsertId($yz_payment_arr);
        }

        return response()->json(compact('qr_img', 'qr_id', 'price', 'payment_id'));
    }

    /*
     * D币统计
     */
    public function statisticDcoin($id)
    {
        $user = User::findOrFail($id);
        $dcoin_statistic = UserDcoinsLog::dcoinStatistic($user->id);
        return view('users.dcoin_statistic', compact('dcoin_statistic', 'user'));
    }

    /*
     * D币明细
     */
    public function dcoinDetail($id)
    {
        $user = User::findOrFail($id);
        $user_dcoin_list = UserDcoinsLog::userDcoinList($user->id);

        return view('users.dcoin_detail', compact('user_dcoin_list', 'user'));
    }

    public function dcoin2point($id, Request $request)
    {
        $user = User::findOrFail($id);
        $dcoin_statistic = UserDcoinsLog::dcoinStatistic($user->id);
        //进行转化
        if (null !== $request->input('dcoin_transfer')) {
            if ($dcoin_statistic['remain_dcoins'] < $request->input('dcoin_transfer')) {
                Flash::error('您的剩余D币不够,可在账户中心充值D币');
                return;
            }
            $point_statistic = UserPointsLog::pointStatistic($user->id);
            try {
                DB::transaction(function () use ($request, $user, $dcoin_statistic, $point_statistic) {
                    //
                    $dcoin_transfer = intval($request->input('dcoin_transfer'), 0);
                    $userDcoinsLog = new UserDcoinsLog();
                    $userDcoinsLog->user_id = $user->id;
                    $userDcoinsLog->type = 2;//消耗
                    $userDcoinsLog->dcoins = -$dcoin_transfer;
                    $userDcoinsLog->remain_dcoins = $dcoin_statistic['remain_dcoins'] - $dcoin_transfer;
                    $userDcoinsLog->reason_type = UserDcoinsLog::REASON_TYPE_DB2POINTS;//D币积分转换
                    $userDcoinsLog->save();

                    $userPointsLog = new UserPointsLog();
                    $userPointsLog->user_id = $user->id;
                    $userPointsLog->type = 1;//增加
                    $userPointsLog->points = $dcoin_transfer * 10;
                    $userPointsLog->remain_points = $point_statistic['remain_points'] + $dcoin_transfer * 10;
                    $userPointsLog->reason_type = UserPointsLog::REASON_TYPE_DB2POINTS;//D币积分转换
                    $userPointsLog->save();
                });
                $point_statistic = UserPointsLog::pointStatistic($user->id);
                return view('users.point_statistic', compact('point_statistic', 'user'));
            } catch (\Illuminate\Database\QueryException $ex) {
                Flash::error('转换失败');
                return view('users.dcoin_2_point', compact('dcoin_statistic', 'user'));
            }

        }
        //否则进入转换页面
        return view('users.dcoin_2_point', compact('dcoin_statistic', 'user'));
    }

    /*
     * 积分统计
     */
    public function statisticPoint($id)
    {
        $user = User::findOrFail($id);
        $point_statistic = UserPointsLog::pointStatistic($user->id);
        return view('users.point_statistic', compact('point_statistic', 'user'));
    }

    /*
     * 积分明细
     */
    public function pointDetail($id)
    {
        $user = User::findOrFail($id);
        $user_point_list = UserPointsLog::userPointList($user->id);

        return view('users.point_detail', compact('user_point_list', 'user'));
    }

    public function replies($id)
    {
        $user = User::findOrFail($id);
        $replies = Reply::whose($user->id)->recent()->paginate(15);

        return view('users.replies', compact('user', 'replies'));
    }

    public function topics($id)
    {
        $user = User::findOrFail($id);
        $topics = Topic::whose($user->id)->withoutArticle()->withoutBoardTopics()->recent()->paginate(30);

        return view('users.topics', compact('user', 'topics'));
    }

    public function articles($id)
    {
        $user = User::findOrFail($id);
        $topics = Topic::whose($user->id)->onlyArticle()->withoutDraft()->recent()->with('blogs')->paginate(30);
        $user->update(['article_count' => $topics->total()]);
        return view('users.articles', compact('user', 'blog', 'topics'));
    }

    public function drafts()
    {
        $user = Auth::user();
        $topics = $user->topics()->onlyArticle()->draft()->recent()->paginate(30);
        $blog = $user->blogs()->first();

        $user->draft_count = $user->topics()->onlyArticle()->draft()->count();
        $user->save();

        return view('users.articles', compact('user', 'blog', 'topics'));
    }

    public function votes($id)
    {
        $user = User::findOrFail($id);
        $topics = $user->votedTopics()->orderBy('pivot_created_at', 'desc')->paginate(30);

        return view('users.votes', compact('user', 'topics'));
    }

    public function translates($id)
    {
        $user = User::findOrFail($id);
        $translates = $user->reviewedTranslates()->with('translateSection.topic')->orderBy('id', 'desc')->paginate(30);

        return view('users.translates', compact('user', 'translates'));
    }

    public function following($id)
    {
        $user = User::findOrFail($id);
        $users = $user->followings()->orderBy('id', 'desc')->paginate(15);

        return view('users.following', compact('user', 'users'));
    }

    public function followers($id)
    {
        $user = User::findOrFail($id);
        $users = $user->followers()->orderBy('id', 'desc')->paginate(15);

        return view('users.followers', compact('user', 'users'));
    }

    public function accessTokens($id)
    {
        if (!Auth::check() || Auth::id() != $id) {
            return redirect(route('users.show', $id));
        }
        $user = User::findOrFail($id);
        $sessions = OAuthSession::where([
            'owner_type' => 'user',
            'owner_id' => Auth::id(),
        ])
            ->with('token')
            ->lists('id') ?: [];

        $tokens = AccessToken::whereIn('session_id', $sessions)->get();

        return view('users.access_tokens', compact('user', 'tokens'));
    }

    public function revokeAccessToken($token)
    {
        $access_token = AccessToken::with('session')->find($token);

        if (!$access_token || !Auth::check() || $access_token->session->owner_id != Auth::id()) {
            Flash::error(lang('Revoke Failed'));
        } else {
            $access_token->delete();
            Flash::success(lang('Revoke success'));
        }

        return redirect(route('users.access_tokens', Auth::id()));
    }

    public function blocking($id)
    {
        $user = User::findOrFail($id);
        $user->is_banned = $user->is_banned == 'yes' ? 'no' : 'yes';
        $user->save();

        // 用户被屏蔽后屏蔽用户所有内容，解封时解封所有内容
        $user->topics()->update(['is_blocked' => $user->is_banned]);
        $user->replies()->update(['is_blocked' => $user->is_banned]);

        return redirect(route('users.show', $id));
    }

    public function editEmailNotify($id)
    {
        $user = User::findOrFail($id);
        $this->authorize('update', $user);

        return view('users.edit_email_notify', compact('user'));
    }

    public function updateEmailNotify($id, Request $request)
    {
        $user = User::findOrFail($id);
        $this->authorize('update', $user);
        $user->email_notify_enabled = $request->email_notify_enabled == 'on' ? 'yes' : 'no';
        $user->save();

        Flash::success(lang('Operation succeeded.'));

        return redirect(route('users.edit_email_notify', $id));
    }

    public function editPassword($id)
    {
        $user = User::findOrFail($id);
        $this->authorize('update', $user);

        return view('users.edit_password', compact('user'));
    }

    public function updatePassword($id, ResetPasswordRequest $request)
    {
        $user = User::findOrFail($id);
        $this->authorize('update', $user);

        $user->password = bcrypt($request->password);
        $user->save();

        Flash::success(lang('Operation succeeded.'));

        return redirect(route('users.edit_password', $id));
    }

    public function githubApiProxy($username)
    {
        $cache_name = 'github_api_proxy_user_' . $username;

        return Cache::remember($cache_name, 1440, function () use ($username) {
            $result = (new GithubUserDataReader())->getDataFromUserName($username);

            return response()->json($result);
        });
    }

    public function regenerateLoginToken()
    {
        if (Auth::check()) {
            Auth::user()->login_token = str_random(rand(20, 32));
            Auth::user()->save();
            Flash::success(lang('Regenerate succeeded.'));
        } else {
            Flash::error(lang('Regenerate failed.'));
        }

        return redirect(route('users.show', Auth::id()));
    }

    public function doFollow($id)
    {
        $user = User::findOrFail($id);

        if (Auth::user()->isFollowing($id)) {
            Auth::user()->unfollow($id);
            app(UserFollowedUser::class)->remove(Auth::user(), $user);
        } else {
            Auth::user()->follow($id);
            app('Phphub\Notification\Notifier')->newFollowNotify(Auth::user(), $user);
            app(UserFollowedUser::class)->generate(Auth::user(), $user);

        }

        $user->update(['follower_count' => $user->followers()->count()]);
        Flash::success(lang('Operation succeeded.'));

        return redirect()->back();
    }

    public function editAvatar($id)
    {
        $user = User::findOrFail($id);
        $this->authorize('update', $user);

        return view('users.edit_avatar', compact('user'));
    }

    public function updateAvatar($id, Request $request)
    {
        $user = User::findOrFail($id);
        $this->authorize('update', $user);

        if ($file = $request->file('avatar')) {
            try {
                $user->updateAvatar($file);
                Flash::success(lang('Update Avatar Success'));
            } catch (ImageUploadException $exception) {
                Flash::error(lang($exception->getMessage()));
            }
        } else {
            Flash::error(lang('Update Avatar Failed'));
        }

        return redirect(route('users.edit_avatar', $id));
    }

    public function sendVerificationMail()
    {
        $user = Auth::user();
//        $job = (new SendActivateMail($user))->onQueue('phphub');
//        $this->dispatch($job);


        $cache_key = 'send_activite_mail_' . $user->id;
        if (Cache::has($cache_key)) {
            Flash::error(lang('The mail send failed! Please try again in 60 seconds.', ['seconds' => (Cache::get($cache_key) - time())]));
        } else {
            if (!$user->email) {
                Flash::error(lang('The mail send failed! Please fill in your email address first.'));
            } else {
                if (!$user->verified) {
                    dispatch(new SendActivateMail($user));
                    Flash::success(lang('The mail sent successfully.'));
                    Cache::put($cache_key, time() + 60, 1);
                }
            }
        }

//        //for debug
//        $user = Auth::user();
//        Mail::send('emails.fake', [], function (Message $message) use($user) { $message->to($user->email)->subject('公司未婚妹子数量报表统计');});
//        exit;
        return redirect()->intended('/');
    }

    public function editSocialBinding($id)
    {
        $user = User::findOrFail($id);
        $this->authorize('update', $user);

        return view('users.edit_social_binding', compact('user'));
    }

    public function buyVip(Requests\BuyVipRequest $request)
    {
        $vipId = $request->id;

        $user = Auth::user();
    }

    public function emailVerificationRequired()
    {
        if (\Auth::user()->verified) {
            return redirect()->intended('/');
        }

        return view('users.emailverificationrequired');
    }

    /*
     * 签到
     */
    public function sign()
    {
        $res = $this->sign_status($addPoints = 5);
        if ($res == -2) {
            return ['status' => '-2', 'points' => 0, 'msg' => '失败'];
        } elseif ($res == -1) {
            return ['status' => '-1', 'msg' => 'not login'];
        } elseif ($res == 0) {
            return ['status' => '0', 'points' => 0, 'msg' => '今天已经签到过了哦!'];
        } elseif ($res == 1) {
            return ['status' => '1', 'points' => $addPoints, 'msg' => lang('Sign successfully')];
        }
    }

    /*
     * 签到状态
     */
    public function signStatus()
    {
        // 判断是否登录
        if (!\Auth::user()) {
            return -1;
        }
        $id = \Auth::user()->id;
        // 判断今天是否签到
        $startTime = date('Y-m-d 00:00:00');
        $endTime = date('Y-m-d 23:59:59');
        $now = date('Y-m-d H:i:s');
        $signRes = UserSignLog::where('user_id', '=', $id)
            ->where('created_at', '>=', $startTime)
            ->where('created_at', '<=', $endTime)
            ->first();
        if (!empty($signRes)) {
            return 0;//已经签到
        }
        return -2;
    }

    private function sign_status($addPoints = 5)
    {
        // 判断是否登录
        if (!\Auth::user()) {
            return -1;
        }
        try {
            $id = \Auth::user()->id;
            // 判断今天是否签到
            $startTime = date('Y-m-d 00:00:00');
            $endTime = date('Y-m-d 23:59:59');
            $now = date('Y-m-d H:i:s');
            $signRes = UserSignLog::where('user_id', '=', $id)
                ->where('created_at', '>=', $startTime)
                ->where('created_at', '<=', $endTime)
                ->first();
            if (!empty($signRes)) {
                return 0;
            }

            DB::beginTransaction();

            // 记录签到
            $addSignData = [
                'user_id' => $id,
                'created_at' => $now,
                'updated_at' => $now
            ];
            UserSignLog::insert($addSignData);

            // 增加积分
            $currentPointsRes = UserPointsLog::getLatestUPLog($id);
            //当前积分数
            $remainPoints = 0;
            if (!empty($currentPointsRes)) {
                $remainPoints = $currentPointsRes['remain_points'];
            }
            $type = 1;

            $addPointsData = [
                'user_id' => $id,
                'type' => $type,
                'points' => $addPoints,
                'remain_points' => $remainPoints + $addPoints,
                'reason_type' => $type,
                'remark' => '签到',
                'created_at' => $now,
                'updated_at' => $now
            ];
            UserPointsLog::insert($addPointsData);
            DB::commit();
            return 1;
        } catch (Exception $e) {
            DB::rollBack();
            return -2;
        }
    }

    //用户登录,在线时长
    public function duration()
    {
        $user = Auth::user();
        if ($user) {
            if (!Cache::has('user_online_tm1-' . $user->id)) {
                Cache::forever('user_online_tm1-' . $user->id, Carbon::now()->subMinute()->getTimestamp());
            }

            //等60s执行一次
            Cache::forever('user_online_tm2-' . $user->id, Carbon::now()->getTimestamp());

            return ['status' => 1, 'tm1' => Cache::get('user_online_tm1-' . $user->id), 'tm2' => Cache::get('user_online_tm2-' . $user->id)];
        }

//        $user = Auth::user();
//        $redis = Redis::connection('default');
//
//        $user_duration =  $redis->llen('local:duration:user_'.$user->id);
//        $now=Carbon::now();
//        if($user_duration){
//            $redis->lset('local:duration:user_'.$user->id, 1,$now);
//        }else{
//            $redis->rpush('local:duration:user_'.$user->id,$now);
//            $redis->rpush('local:duration:user_'.$user->id,$now);
//        }
    }


}
